import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

public class InvokeDynamicTest {
	public static void testMethod(String s) {
		System.out.println("hello " + s);
	}

	public static void main(String[] args) throws Throwable {
		INDY_BootstrapMethod().invokeExact("world");
	}

	private static MethodHandle INDY_BootstrapMethod() throws Throwable {
		CallSite cs = (CallSite)MH_BootstrapMethod().invokeWithArguments(MethodHandles.lookup(), "testMethod",
//				MethodType.fromMethodDescriptorString("(Ljava/lang/String;)V", null));
				MethodType.methodType(void.class, String.class));
		return cs.dynamicInvoker();
	}

	private static MethodHandle MH_BootstrapMethod() throws Throwable {
		return MethodHandles.lookup().findStatic(InvokeDynamicTest.class, "BootstrapMethod", MT_BootstrapMethod());
	}

	private static MethodType MT_BootstrapMethod() {
//		return MethodType.fromMethodDescriptorString(
//				"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)" +
//						"Ljava/lang/invoke/CallSite;", null);
		return MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
	}

	public static CallSite BootstrapMethod(MethodHandles.Lookup lookup, String name, MethodType mt) throws Throwable {
		return new ConstantCallSite(lookup.findStatic(InvokeDynamicTest.class, name, mt));
	}
}
